﻿#include "modbusrtucontroller.h"
#include <QVariant>
ModbusRtuController::ModbusRtuController(QObject *parent) : QObject(parent)
{

}

ModbusRtuController::~ModbusRtuController()
{
    if(pUsart != nullptr)
    {
        delete pUsart;
        pUsart = nullptr;
    }
}

bool ModbusRtuController::modbus_02SingleRead(uint8_t node, uint16_t reg, bool &result)
{
    QByteArray senddata;
    senddata.resize(8);
    senddata[0] = node;
    senddata[1] = MODBUSWORD::DIR02;
    senddata[2] = (uint8_t)(reg>>8);
    senddata[3] = (uint8_t)reg;
    senddata[4] = 0;
    senddata[5] = 1;

    pUsart->CRC_16(senddata);
    QByteArray recievedata = pUsart->sendAsync(senddata);
    if(!pUsart->CRC_16(recievedata)) return false;

    return true;
}

bool ModbusRtuController::modbus_02MultiRead(uint8_t node, uint16_t reg, int16_t count, QVector<bool> &result)
{
    QByteArray senddata;
    senddata.resize(8);
    senddata[0] = node;
    senddata[1] = MODBUSWORD::DIR02;
    senddata[2] = (uint8_t)(reg>>8);
    senddata[3] = (uint8_t)reg;
    senddata[4] = (uint8_t)(count>>8);
    senddata[5] = (uint8_t)count;

    pUsart->CRC_16(senddata);
    QByteArray recievedata = pUsart->sendAsync(senddata);
    if(!pUsart->CRC_16(recievedata)) return false;
    int16_t countn = 0;
    for(int i=0;i<recievedata[2];++i){
        uint8_t cnt = 0x01;
        for(int j=0;j<8;++j){
            result.push_back(recievedata[3+i] & cnt);
            cnt = cnt<<1;
            if(++countn >= count)   return true;
        }
    }
    return  true;
}

bool ModbusRtuController::modbus_05SingleWrite(uint8_t node, uint16_t reg, const bool &value)
{
    QByteArray senddata;
    senddata.resize(8);
    senddata[0] = node;
    senddata[1] = MODBUSWORD::DOW05;
    senddata[2] = (uint8_t)(reg>>8);
    senddata[3] = (uint8_t)reg;
    if(value){
        senddata[4] = 0xFF;
        senddata[5] = 0x00;
    }
    else{
        senddata[4] = 0x00;
        senddata[5] = 0x00;
    }

    pUsart->CRC_16(senddata);
    QByteArray recievedata = pUsart->sendAsync(senddata);
    if(!pUsart->CRC_16(recievedata)) return false;

    return  true;
}

bool ModbusRtuController::modbus_SingleRead(uint8_t node, uint16_t reg, uint16_t count,QByteArray& recievedata)
{
    QByteArray senddata;
    senddata.resize(8);
    senddata[0] = node;
    senddata[1] = word_SingleRead;
    senddata[2] = (uint8_t)(reg>>8);
    senddata[3] = (uint8_t)reg;
    senddata[4] = (uint8_t)(count>>8);
    senddata[5] = (uint8_t)count;

    pUsart->CRC_16(senddata);
    recievedata = pUsart->sendAsync(senddata);
    return pUsart->CRC_16(recievedata);
}

bool ModbusRtuController::modbus_SingleWrite(uint8_t node, uint16_t reg, uint16_t value)
{
    QByteArray senddata;
    senddata.resize(8);
    senddata[0] = node;
    senddata[1] = word_SingleWrite;
    senddata[2] = (uint8_t)(reg>>8);
    senddata[3] = (uint8_t)reg;
    senddata[4] = (uint8_t)(value>>8);
    senddata[5] = (uint8_t)value;

    pUsart->CRC_16(senddata);
    QByteArray recievedata = pUsart->sendAsync(senddata);
    if(!pUsart->CRC_16(recievedata))
        return false;
    if(recievedata != senddata)
        return false;
    return true;
}

bool ModbusRtuController::modbus_MultiWrite(uint8_t node, uint16_t reg, QVector<uint16_t> values)
{
    QByteArray senddata;
    senddata.resize(9+values.size()*2);
    senddata[0] = node;
    senddata[1] = word_MultiWrite;
    senddata[2] = (uint8_t)(reg>>8);
    senddata[3] = (uint8_t)reg;
    senddata[4] = (uint8_t)(values.size()>>8);
    senddata[5] = (uint8_t)values.size();
    senddata[6] = values.size()*2;
    for(int i=0;i<values.size();i++)
    {
        senddata[6+2*i] = (uint8_t)(values[i]>>8);
        senddata[7+2*i] = (uint8_t)(values[i]);
    }

    pUsart->CRC_16(senddata);
    QByteArray recievedata = pUsart->sendAsync(senddata);
    if(!pUsart->CRC_16(recievedata))
        return false;
    if(recievedata.left(6) != senddata.left(6))
        return false;
    return true;
}

bool ModbusRtuController::ModbusUsart_Init(QString com, int band, int dataBits, int stopBits, int parity)
{
    pUsart = new SerialController();
    return pUsart->SerialInit(com,band,dataBits,stopBits,parity);
}

bool Modbus_WriteCmd::excute(ModbusRtuController *myModbus)
{
    switch (KeyWord) {
    case ModbusRtuController::MODBUSWORD::DOW05:
        if(Count == 1){
            return myModbus->modbus_05SingleWrite(Node,RegAddr,RegsValue[0].toBool());
        }
        else{

        }
        break;

    default:
        return false;
    }
    return false;
}
